package br.ufmg.vod.wbr;

public class EdgeUtil {
	
	public static final long MAX_VERTEX = 0x7FFFFFFFl;
	
	public static final long IS_SOURCE_R_MASK = 0x80000000l;
	public static final long VERTEX_R_MASK = 0x7FFFFFFFl;
	
	public static final long IS_SOURCE_L_MASK = IS_SOURCE_R_MASK << 32;
	public static final long VERTEX_L_MASK = VERTEX_R_MASK << 32;
	
	private static boolean isSourceL(long edge){
		return (edge&IS_SOURCE_L_MASK) != 0;
	}
	
	private static boolean isSourceR(long edge){
		return !isSourceL(edge);
	}
	private static int getL(long edge){
		return (int) (edge>>32&VERTEX_R_MASK);
	}
	
	private static int getR(long edge){
		return (int) (edge&VERTEX_R_MASK);
	}
	
	
	public static boolean isSource( int v, long edge ){
		assert v <= MAX_VERTEX;
		assert v >= 0;
		return isSourceL(edge) ? getL(edge) == v: getR(edge) == v;
	}
	
	public static boolean isDest( int v, long edge ){
		assert v <= MAX_VERTEX;
		assert v >= 0;
		return isSourceR(edge) ? getL(edge) == v: getR(edge) == v;
	}
	
	public static int getSource( long edge ){
		return isSourceL(edge) ? getL(edge) : getR(edge);
	}
	
	public static int getDest( long edge ){
		return isSourceL(edge) ? getR(edge) : getL(edge);
	}
	
	public static long generateEdgeId( int u, int v ){
		assert u <= MAX_VERTEX;
		assert v <= MAX_VERTEX;
		assert u >= 0;
		assert v >= 0;
		
		if( u <= v )
			return ((long)u<<32) | (v&VERTEX_R_MASK) | IS_SOURCE_L_MASK;
		else
			return ((long)v<<32) | (u&VERTEX_R_MASK) | IS_SOURCE_R_MASK;
	}
	
	public static void main(String[] args) {

		
		long edge = generateEdgeId(3, 17);
		System.out.println(Long.toBinaryString(edge));
		System.out.println(getSource(edge));
		System.out.println(getDest(edge));
		System.out.println(isSourceL(edge));
		System.out.println(isSourceR(edge));
		
		edge = generateEdgeId(17, 3);
		System.out.println(Long.toBinaryString(edge));
		System.out.println(getSource(edge));
		System.out.println(getDest(edge));
		System.out.println(isSourceL(edge));
		System.out.println(isSourceR(edge));
	}

}
